﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;

using ProjectBase.Core;
using ProjectBase.Tools.Publishing;
using ProjectBase.Tools.Publishing.Handlers.ExceptionHandler;
using $safeprojectname$.Infrastructure.Exceptions;
using $safeprojectname$.Infrastructure.Factories;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace $safeprojectname$.Publishing.Handlers
{
    [TestClass]
    public class WriteToEventLogTest : TestBase
    {
        [TestMethod]
        public void DefaultSettings_ForUnknownException_Passed()
        {
            LoggingTargets.RestoreLogs();

            var settings = ExceptionConfigurationReader.DefaultExceptionHandlerSettings();

            var handler = new ExceptionPublishingHandler();
            handler.Init(settings);

            var exception = new Exception("MyException", new Exception("MyInnerException"));
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.First();
            Assert.IsTrue(entry.EntryType.Equals(EventLogEntryType.FailureAudit), "entry.EntryType = " + entry.EntryType);
            Assert.IsTrue(entry.InstanceId.Equals(7777), "entry.InstanceId =" + entry.InstanceId);
            Assert.IsTrue(entry.Message.Contains("*********************************************"));
        }

        [TestMethod]
        public void PublishException_Passed()
        {
            LoggingTargets.RestoreLogs();

            var handler = HandlerFactory.DefaultHandler();
            var exception = new Exception("MyException", new Exception("MyInnerException"));
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.First();
            Assert.IsTrue(entry.EntryType.Equals(EventLogEntryType.Error));
            Assert.IsTrue(entry.Message.Contains("*********************************************"));
        }

        [TestMethod]
        public void ExceptionsMissing_Passed()
        {
            LoggingTargets.RestoreLogs();

            var handler = HandlerFactory.HandlerWithExceptionMissing();

            var exception = new ChildException("MyException", new BaseException());
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.First();
            Assert.IsTrue(entry.EntryType.Equals(EventLogEntryType.Error));
            Assert.IsTrue(entry.InstanceId.Equals(9999));
            Assert.IsTrue(entry.Message.Contains("*********************************************"));
        }

        [TestMethod]
        public void MissingHandlerSettings_Passed()
        {
            LoggingTargets.RestoreLogs();

            var settings = ExceptionConfigurationReader.NotCompleteExceptionHandlerSettings();

            var handler = new ExceptionPublishingHandler();
            handler.Init(settings);

            Assert.IsTrue(handler.LogName.IsEqual("Application"));
            Assert.IsTrue(handler.ApplicationName.IsEqual("ProjectBase"));
        }

        [TestMethod]
        public void FluentHandlerConfiguration_Passed()
        {
            LoggingTargets.RestoreLogs();

            var handler = new ExceptionPublishingHandler();
            var element = ExceptionConfigurationReader.NotCompleteExceptionHandlerSettings();
            var configuration = new ConfigurationReader().Create("Publishing.config");

            handler.Init("ProjectBaseApplication", "ProjectBaseLog", configuration);

            var exception = new ChildException("MyException", new BaseException());
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.First();
            Assert.IsTrue(entry.InstanceId.Equals(5505));
            Assert.IsTrue(entry.Message.Contains("ChildException"));
            Assert.IsTrue(entry.EntryType.Equals(EventLogEntryType.FailureAudit));
        }

        [TestMethod]
        public void DoNotPublish_Passed()
        {
            LoggingTargets.RestoreLogs();

            var handler = new ExceptionPublishingHandler();
            var element = ExceptionConfigurationReader.NotCompleteExceptionHandlerSettings();
            var configuration = new ConfigurationReader().Create("Publishing.config");
            configuration.DoNotPublish = true;

            handler.Init("ProjectBaseApplication", "ProjectBaseLog", configuration);

            var exception = new ChildException("MyException", new BaseException());
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.FirstOrDefault();
            Assert.IsTrue(entry.IsNull());
        }
        [TestMethod]
        public void FluentlySetConfiguration_Passed()
        {
            LoggingTargets.RestoreLogs();

            var handler = new ExceptionPublishingHandler();
            var element = ExceptionConfigurationReader.MissingExceptionHandlerSettings();

            var configuration = new ConfigurationReader().Create("Publishing.config");
            configuration.DefaultEventId = 8888;
            configuration.DefaultEventLogEntryType = EventLogEntryType.SuccessAudit;
            configuration.Exceptions = new List<ExceptionSettings>();

            handler.Init("ProjectBaseApplication", "ProjectBaseLog", configuration);

            var exception = new ChildException("MyException", new BaseException());
            handler.Handle(this, "Exception", exception);

            // win event log
            var entry = LoggingTargets.TestEventLogEntries.First();
            Assert.IsTrue(entry.EntryType.Equals(EventLogEntryType.SuccessAudit));
            Assert.IsTrue(entry.InstanceId.Equals(8888));
            Assert.IsTrue(entry.Message.Contains("ChildException"));
        }

        #region Init

        // You can use the following additional attributes as you write your tests:

        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }

        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }

        [TestInitialize]
        public override void MyTestInitialize()
        {
            base.MyTestInitialize(); // Use TestInitialize to run code before running each test
        }

        [TestCleanup]
        public override void MyTestCleanup()
        {
            base.MyTestCleanup(); // Use TestCleanup to run code after each test has run
        }
        #endregion Init
    }
}
